package com.gitee.wsl.net.server

import com.gitee.wsl.transform.validator.Validator
import io.ktor.http.HttpStatusCode
import io.ktor.serialization.kotlinx.json.DefaultJson
import io.ktor.serialization.kotlinx.json.json
import io.ktor.server.application.Application
import io.ktor.server.application.install
import io.ktor.server.plugins.cachingheaders.CachingHeaders
import io.ktor.server.plugins.cachingheaders.CachingHeadersConfig
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.plugins.requestvalidation.RequestValidation
import io.ktor.server.plugins.requestvalidation.RequestValidationConfig
import io.ktor.server.plugins.requestvalidation.RequestValidationException
import io.ktor.server.plugins.requestvalidation.ValidationResult
import io.ktor.server.plugins.statuspages.StatusPages
import io.ktor.server.response.respond
import io.ktor.server.sessions.Sessions
import io.ktor.server.sessions.SessionsConfig
import io.ktor.server.websocket.WebSockets
import io.ktor.server.websocket.WebSockets.WebSocketOptions
import kotlinx.serialization.json.Json


fun Application.session(pluginConfig: SessionsConfig.()->Unit){
    install(Sessions,pluginConfig)
}

fun Application.webSockets(pluginConfig: WebSocketOptions.() -> Unit){
    install(WebSockets,pluginConfig)
}

fun Application.cacheHeaders(pluginConfig: CachingHeadersConfig.() -> Unit){
    install(CachingHeaders,pluginConfig)
}

fun Application.jsonAble(json: Json = DefaultJson,){
    install(ContentNegotiation) {
        json(json)
    }
}

fun Application.validateAble(config: RequestValidationConfig.()->Unit){
    install(RequestValidation) {
        config()
        validate {
            filter { body ->
                Validator.validatorsRegistry.containsKey(body::class)
            }
            validation { body ->
                var result:ValidationResult = ValidationResult.Valid
                Validator.validateWithResult(body).onFailure {
                    result = ValidationResult.Invalid(it.message?:"")
                }
                result
            }
        }
    }

    install(StatusPages) {
        exception<RequestValidationException> { call, cause ->
            call.respond(HttpStatusCode.BadRequest, cause. reasons. joinToString())
        }
    }
}